<?php

namespace App\Http\Controllers\Admin\Finance\Receivable;

use App\Http\Controllers\Controller;
use App\Models\finance\ReceivableTemplate2Model;
use App\Models\TakeOrderModel;
use App\Exports\ReceivableTemplate2Export;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Validator;
use Maatwebsite\Excel\Facades\Excel;

class Template2 extends Controller
{
    /**
     * 模板2应收账款列表
     *
     * @param Request $request
     * @return JsonResponse
     */
    public function list(Request $request): JsonResponse
    {
        $query = ReceivableTemplate2Model::with(['customer', 'take_order', 'create_admin']);
        
        // 筛选条件
        if ($request->filled('take_order_id')) {
            $query->where('take_order_id', $request->input('take_order_id'));
        }
        
        if ($request->filled('customer_id')) {
            $query->where('customer_id', $request->input('customer_id'));
        }
        
        if ($request->filled('flight_number')) {
            $query->where('flight_number', 'like', '%' . $request->input('flight_number') . '%');
        }
        
        if ($request->filled('departure')) {
            $query->where('departure', 'like', '%' . $request->input('departure') . '%');
        }
        
        if ($request->filled('destination')) {
            $query->where('destination', 'like', '%' . $request->input('destination') . '%');
        }
        
        if ($request->filled('status')) {
            $query->where('status', $request->input('status'));
        }
        
        if ($request->filled('currency')) {
            $query->where('currency', $request->input('currency'));
        }
        
        if ($request->filled('flight_date_start') && $request->filled('flight_date_end')) {
            $query->whereBetween('flight_date', [$request->input('flight_date_start'), $request->input('flight_date_end')]);
        }
        
        if ($request->filled('date_start') && $request->filled('date_end')) {
            $query->whereBetween('created_at', [$request->input('date_start'), $request->input('date_end') . ' 23:59:59']);
        }

        if ($request->filled('take_order_sn')) {
            $takeOrderIds = TakeOrderModel::where('sn', 'like', '%' . $request->input('take_order_sn') . '%')
                ->pluck('id')
                ->toArray();
            if (!empty($takeOrderIds)) {
                $query->whereIn('take_order_id', $takeOrderIds);
            }
        }
        
        // 分页
        $per_page = $request->input('per_page', 15);
        $list = $query->orderBy('id', 'desc')->paginate($per_page);
        
        return $this->success([
            'list' => $list->items(),
            'total' => $list->total(),
        ]);
    }
    
    /**
     * 添加模板2应收账款
     *
     * @param Request $request
     * @return JsonResponse
     */
    public function add(Request $request): JsonResponse
    {
        $params = $request->all();
        $validator = Validator::make($params, [
            'airway_bill' => 'required|string|max:100',
            'customer_id' => 'required|exists:t_customer,id',
            'flight_date' => 'required|date',
            'flight_number' => 'required|string|max:50',
            'departure' => 'required|string|max:100',
            'destination' => 'required|string|max:100',
            'pieces' => 'nullable|integer|min:0',
            'gross_weight' => 'nullable|numeric|min:0',
            'volume_weight' => 'nullable|numeric|min:0',
            'chargeable_weight' => 'nullable|numeric|min:0',
            'pick_up_fee' => 'nullable|numeric|min:0',
            'handling_charge' => 'nullable|numeric|min:0',
            'customs_declaration_fee' => 'nullable|numeric|min:0',
            'mawb_documents_fee' => 'nullable|numeric|min:0',
            'total' => 'nullable|numeric|min:0',
            'currency' => 'required|string|max:20'
        ], [
            'airway_bill.required' => '提单号不能为空',
            'airway_bill.string' => '提单号必须是字符串',
            'airway_bill.max' => '提单号不能超过100个字符',
            'customer_id.required' => '客户不能为空',
            'customer_id.exists' => '客户不存在',
            'flight_date.required' => '航班日期不能为空',
            'flight_date.date' => '航班日期格式不正确',
            'flight_number.required' => '航班号不能为空',
            'flight_number.string' => '航班号必须是字符串',
            'flight_number.max' => '航班号不能超过50个字符',
            'departure.required' => '始发地不能为空',
            'departure.string' => '始发地必须是字符串',
            'departure.max' => '始发地不能超过100个字符',
            'destination.required' => '目的地不能为空',
            'destination.string' => '目的地必须是字符串',
            'destination.max' => '目的地不能超过100个字符',
            'pieces.integer' => '件数必须是整数',
            'pieces.min' => '件数不能小于0',
            'gross_weight.numeric' => '毛重必须是数字',
            'gross_weight.min' => '毛重不能小于0',
            'volume_weight.numeric' => '体积重必须是数字',
            'volume_weight.min' => '体积重不能小于0',
            'chargeable_weight.numeric' => '计费重必须是数字',
            'chargeable_weight.min' => '计费重不能小于0',
            'pick_up_fee.numeric' => '提货费必须是数字',
            'pick_up_fee.min' => '提货费不能小于0',
            'handling_charge.numeric' => '操作费必须是数字',
            'handling_charge.min' => '操作费不能小于0',
            'customs_declaration_fee.numeric' => '报关费必须是数字',
            'customs_declaration_fee.min' => '报关费不能小于0',
            'mawb_documents_fee.numeric' => '主单文件费必须是数字',
            'mawb_documents_fee.min' => '主单文件费不能小于0',
            'total.numeric' => '总额必须是数字',
            'total.min' => '总额不能小于0',
            'currency.required' => '币种不能为空',
            'currency.string' => '币种必须是字符串',
            'currency.max' => '币种不能超过20个字符',
        ]);
        
        if ($validator->fails()) {
            return $this->error($validator->errors()->first());
        }

        // 如果提供了主单号，查询对应的主单ID
        $take_order_id = null;
        if ($request->filled('airway_bill')) {
            $takeOrder = TakeOrderModel::where('sn', $request->input('airway_bill'))->first();
            if ($takeOrder) {
                $take_order_id = $takeOrder->id;
            }
        }
        
        try {
            DB::beginTransaction();
            
            $receivable = new ReceivableTemplate2Model();
            $receivable->take_order_id = $take_order_id;
            $receivable->customer_id = $params['customer_id'];
            $receivable->flight_date = $params['flight_date'];
            $receivable->flight_number = $params['flight_number'];
            $receivable->departure = $params['departure'];
            $receivable->destination = $params['destination'];
            $receivable->pieces = $params['pieces'] ?? 0;
            $receivable->gross_weight = $params['gross_weight'] ?? 0;
            $receivable->volume_weight = $params['volume_weight'] ?? 0;
            $receivable->chargeable_weight = $params['chargeable_weight'] ?? 0;
            $receivable->pick_up_fee = $params['pick_up_fee'] ?? 0;
            $receivable->handling_charge = $params['handling_charge'] ?? 0;
            $receivable->customs_declaration_fee = $params['customs_declaration_fee'] ?? 0;
            $receivable->mawb_documents_fee = $params['mawb_documents_fee'] ?? 0;
            $receivable->total = $params['total'] ?? $this->calculateTotal($params);
            $receivable->currency = $params['currency'];
            $receivable->status = ReceivableTemplate2Model::STATUS_UNPAID;
            $receivable->created_admin_id = Auth::id();
            $receivable->save();
            
            DB::commit();
            
            return $this->success($receivable, '添加成功');
        } catch (\Exception $e) {
            DB::rollBack();
            return $this->error('添加失败：' . $e->getMessage());
        }
    }
    
    /**
     * 更新模板2应收账款
     *
     * @param Request $request
     * @param int $id
     * @return JsonResponse
     */
    public function update(Request $request, int $id): JsonResponse
    {
        $receivable = ReceivableTemplate2Model::find($id);
        
        if (!$receivable) {
            return $this->error('记录不存在');
        }
        
        $params = $request->all();
        $validator = Validator::make($params, [
            'airway_bill' => 'sometimes|required|string|max:100',
            'customer_id' => 'sometimes|required|exists:t_customer,id',
            'flight_date' => 'sometimes|required|date',
            'flight_number' => 'sometimes|required|string|max:50',
            'departure' => 'sometimes|required|string|max:100',
            'destination' => 'sometimes|required|string|max:100',
            'pieces' => 'nullable|integer|min:0',
            'gross_weight' => 'nullable|numeric|min:0',
            'volume_weight' => 'nullable|numeric|min:0',
            'chargeable_weight' => 'nullable|numeric|min:0',
            'pick_up_fee' => 'nullable|numeric|min:0',
            'handling_charge' => 'nullable|numeric|min:0',
            'customs_declaration_fee' => 'nullable|numeric|min:0',
            'mawb_documents_fee' => 'nullable|numeric|min:0',
            'total' => 'nullable|numeric|min:0',
            'currency' => 'sometimes|required|string|max:20',
            'status' => 'nullable|in:1,2,3',
        ], [
            'airway_bill.required' => '提单号不能为空',
            'airway_bill.string' => '提单号必须是字符串',
            'airway_bill.max' => '提单号不能超过100个字符',
            'customer_id.required' => '客户不能为空',
            'customer_id.exists' => '客户不存在',
            'flight_date.required' => '航班日期不能为空',
            'flight_date.date' => '航班日期格式不正确',
            'flight_number.required' => '航班号不能为空',
            'flight_number.string' => '航班号必须是字符串',
            'flight_number.max' => '航班号不能超过50个字符',
            'departure.required' => '始发地不能为空',
            'departure.string' => '始发地必须是字符串',
            'departure.max' => '始发地不能超过100个字符',
            'destination.required' => '目的地不能为空',
            'destination.string' => '目的地必须是字符串',
            'destination.max' => '目的地不能超过100个字符',
            'pieces.integer' => '件数必须是整数',
            'pieces.min' => '件数不能小于0',
            'gross_weight.numeric' => '毛重必须是数字',
            'gross_weight.min' => '毛重不能小于0',
            'volume_weight.numeric' => '体积重必须是数字',
            'volume_weight.min' => '体积重不能小于0',
            'chargeable_weight.numeric' => '计费重必须是数字',
            'chargeable_weight.min' => '计费重不能小于0',
            'pick_up_fee.numeric' => '提货费必须是数字',
            'pick_up_fee.min' => '提货费不能小于0',
            'handling_charge.numeric' => '操作费必须是数字',
            'handling_charge.min' => '操作费不能小于0',
            'customs_declaration_fee.numeric' => '报关费必须是数字',
            'customs_declaration_fee.min' => '报关费不能小于0',
            'mawb_documents_fee.numeric' => '主单文件费必须是数字',
            'mawb_documents_fee.min' => '主单文件费不能小于0',
            'total.numeric' => '总额必须是数字',
            'total.min' => '总额不能小于0',
            'currency.required' => '币种不能为空',
            'currency.string' => '币种必须是字符串',
            'currency.max' => '币种不能超过20个字符',
            'status.in' => '状态值无效',
        ]);
        
        if ($validator->fails()) {
            return $this->error($validator->errors()->first());
        }
        
        try {
            DB::beginTransaction();
            
            // 如果更新主单号，需要先查询对应的主单ID
            if ($request->filled('airway_bill')) {
                $takeOrder = TakeOrderModel::where('sn', $request->input('airway_bill'))->first();
                if ($takeOrder) {
                    $receivable->take_order_id = $takeOrder->id;
                } else {
                    $receivable->take_order_id = null;
                }
            }
            
            // 更新字段
            $fields = [
                'customer_id', 'flight_date', 'flight_number',
                'departure', 'destination', 'pieces', 'gross_weight',
                'volume_weight', 'chargeable_weight', 'pick_up_fee', 'handling_charge',
                'customs_declaration_fee', 'mawb_documents_fee', 'total',
                'currency', 'status'
            ];
            
            foreach ($fields as $field) {
                if ($request->filled($field)) {
                    $receivable->$field = $request->input($field);
                }
            }
            
            // 如果未提供总额但提供了其他费用字段，重新计算总额
            if (!$request->filled('total') && $this->hasFeeFieldsUpdated($request->all())) {
                $receivable->total = $this->calculateTotal($receivable->toArray());
            }
            
            $receivable->save();
            
            DB::commit();
            
            return $this->success($receivable, '更新成功');
        } catch (\Exception $e) {
            DB::rollBack();
            return $this->error('更新失败：' . $e->getMessage());
        }
    }
    
    /**
     * 删除模板2应收账款
     *
     * @param int $id
     * @return JsonResponse
     */
    public function delete(int $id): JsonResponse
    {
        $receivable = ReceivableTemplate2Model::find($id);
        
        if (!$receivable) {
            return $this->error('记录不存在');
        }
        
        try {
            $receivable->delete();
            return $this->success([], '删除成功');
        } catch (\Exception $e) {
            return $this->error('删除失败：' . $e->getMessage());
        }
    }
    
    /**
     * 判断是否有费用字段被更新
     *
     * @param array $data
     * @return bool
     */
    private function hasFeeFieldsUpdated(array $data): bool
    {
        $feeFields = [
            'pick_up_fee', 'handling_charge', 'customs_declaration_fee', 'mawb_documents_fee'
        ];
        
        foreach ($feeFields as $field) {
            if (isset($data[$field])) {
                return true;
            }
        }
        
        return false;
    }
    
    /**
     * 计算总金额
     *
     * @param array $data
     * @return float
     */
    private function calculateTotal(array $data): float
    {
        $total = 0;
        
        $feeFields = [
            'pick_up_fee', 'handling_charge', 'customs_declaration_fee', 'mawb_documents_fee'
        ];
        
        foreach ($feeFields as $field) {
            if (isset($data[$field]) && is_numeric($data[$field])) {
                $total += floatval($data[$field]);
            }
        }
        
        return round($total, 2);
    }
    
    /**
     * 导出模板2应收账款
     *
     * @param Request $request
     * @return \Symfony\Component\HttpFoundation\BinaryFileResponse
     */
    public function export(Request $request)
    {
        return Excel::download(new ReceivableTemplate2Export($request), '应收账款模板2_' . date('Y-m-d_H-i-s') . '.xlsx');
    }
} 